package com.nq.service.impl;


import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileNameUtil;
import com.nq.activaity.entity.StIntegralTask;
import com.nq.common.SystemVersionEnum;
import com.nq.dao.*;
import com.nq.dao.activaity.StIntegralTaskMapper;
import com.nq.pojo.*;
import com.nq.pojo.vo.UserRechargeVo;
import com.nq.service.*;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.nq.common.ServerResponse;
import com.nq.utils.DateTimeUtil;
import com.nq.utils.DateUtils;
import com.nq.utils.KeyUtils;
import com.nq.utils.email.SendHTMLMail;
import com.nq.utils.redis.RedisShardedPoolUtils;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import com.nq.utils.smsUtil.AbroadSmsUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("iUserRechargeService")
public class UserRechargeServiceImpl implements IUserRechargeService {
    private static final Logger log = LoggerFactory.getLogger(UserRechargeServiceImpl.class);

    @Value("${spring.profiles.active}")
    private String active;

    @Autowired
    UserRechargeMapper userRechargeMapper;
    @Resource
    private LogEditTransactionRecordsMapper logEditTransactionRecordsMapper;

    @Autowired
    IUserService iUserService;

    @Autowired
    UserMapper userMapper;

    @Autowired
    IAgentUserService iAgentUserService;
    @Autowired
    AgentUserMapper agentUserMapper;
    @Autowired
    ISiteSettingService iSiteSettingService;
    @Autowired
    UserCashDetailMapper userCashDetailMapper;
    @Resource
    private StIntegralTaskMapper integralTaskMapper;

    @Autowired
    ISiteInfoService iSiteInfoService;

    @Autowired
    SmsService smsService;

    @Resource
    private SendHTMLMail sendHTMLMail;

    public ServerResponse checkInMoney(int maxOrder, Integer userId) {
        int count = this.userRechargeMapper.checkInMoney(0, userId);

        if (count > maxOrder) {
            return ServerResponse.createByErrorMsg("You can only make "+maxOrder+" deposits in an hour.");
        }
        return ServerResponse.createBySuccess();
    }


    public ServerResponse inMoney(String amt, String payChannel, Integer payId, String file, HttpServletRequest request) {
        if (StringUtils.isBlank(amt) || StringUtils.isBlank(payChannel) || null == payId) {
            return ServerResponse.createByErrorMsg("Parameters cannot be empty.");
        }

        SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting();
        if (siteSetting == null) {
            return ServerResponse.createByErrorMsg("The set is not initialized.");
        }
        if ((new BigDecimal(siteSetting.getChargeMinAmt() + "")).compareTo(new BigDecimal(amt)) == 1) {
            return ServerResponse.createByErrorMsg("The recharge amount must not be less than $"+ siteSetting.getChargeMinAmt() +".");
        }


        SiteInfo siteInfo = null;
        ServerResponse serverResponseInfo = this.iSiteInfoService.getInfo();
        if (serverResponseInfo.isSuccess()) {
            siteInfo = (SiteInfo) serverResponseInfo.getData();
        } else {
            return serverResponseInfo;
        }

        User user = this.iUserService.getCurrentRefreshUser(request);
        if (user.getIsActive().intValue() != 2) {
            return ServerResponse.createByErrorMsg("Recharge cannot be initiated without real-name authentication.");
        }


        ServerResponse serverResponse = checkInMoney(10, user.getId());
        if (!serverResponse.isSuccess()) {
            return serverResponse;
        }


        UserRecharge userRecharge = new UserRecharge();

        userRecharge.setUserId(user.getId());
        userRecharge.setNickName(user.getRealName());
        userRecharge.setAgentId(user.getAgentId());

        String ordersn = KeyUtils.getRechargeOrderSn();
        userRecharge.setOrderSn(ordersn);
        userRecharge.setOrderDesc(file);
        userRecharge.setPayChannel(payChannel);
        userRecharge.setPayAmt(new BigDecimal(amt));
        userRecharge.setOrderStatus(Integer.valueOf(0));
        userRecharge.setAddTime(new Date());
        userRecharge.setPayId(payId);

        int insertCount = this.userRechargeMapper.insert(userRecharge);
        if (insertCount > 0) {
            return ServerResponse.createBySuccessMsg(ordersn);
        }
        return ServerResponse.createByErrorMsg("Failed to create a payment order.");
    }


    public ServerResponse findUserRechargeByOrderSn(String orderSn) {
        UserRecharge userRecharge = this.userRechargeMapper.findUserRechargeByOrderSn(orderSn);
        if (userRecharge != null) {
            return ServerResponse.createBySuccess(userRecharge);
        }
        return ServerResponse.createByErrorMsg("I can't find the recharge order.");
    }


    @Transactional
    public ServerResponse chargeSuccess(UserRecharge userRecharge) throws Exception {
        log.info("充值订单 确认成功操作 id = {}", userRecharge.getId());

        if (userRecharge.getOrderStatus().intValue() != 0) {
            return ServerResponse.createByErrorMsg("The order status cannot be modified repeatedly.");
        }


        User user = this.userMapper.selectByPrimaryKey(userRecharge.getUserId());
        if (user == null) {
            return ServerResponse.createByErrorMsg("User does not exist");
        }
        BigDecimal userAmt_before = user.getUserAmt();
        BigDecimal enableAmt_before = user.getEnableAmt();
//        user.setUserAmt(userAmt_before.add(userRecharge.getPayAmt()));
        user.setEnableAmt(enableAmt_before.add(userRecharge.getPayAmt()));
        int updateCount = this.userMapper.updateByPrimaryKeySelective(user);
        if (updateCount > 0) {
            log.info("1.修改用户资金成功");
        } else {
            return ServerResponse.createByErrorMsg("Failed, failed to modify user funds");
        }


        userRecharge.setOrderStatus(Integer.valueOf(1));
        userRecharge.setPayTime(new Date());
        int updateCCount = this.userRechargeMapper.updateByPrimaryKeySelective(userRecharge);
        if (updateCCount > 0) {
            log.info("2.修改订单状态成功");
        } else {
            throw new Exception("2. Failed to modify order status!");
        }

        UserCashDetail ucd = new UserCashDetail();
        ucd.setAgentId(user.getAgentId());
        ucd.setAgentName(user.getAgentName());
        ucd.setUserId(user.getId());
        ucd.setUserName(user.getRealName());
        ucd.setDeType("User recharge");
        ucd.setDeAmt(userRecharge.getPayAmt());
        ucd.setDeSummary("The user recharges successfully, and the total amount before the recharge:" + userAmt_before + ",userAmt:" + user.getUserAmt() + ",enableAmt_before:" + enableAmt_before + ",enableAmt:" + user
                .getEnableAmt());

        ucd.setAddTime(new Date());
        ucd.setIsRead(Integer.valueOf(0));
        int insertCount = this.userCashDetailMapper.insert(ucd);
        if (insertCount > 0) {
            return ServerResponse.createBySuccessMsg("Successfully recharged！");
        }
        return ServerResponse.createByErrorMsg("Failed to recharge");
    }


    public ServerResponse chargeFail(UserRecharge userRecharge) throws Exception {
        if (userRecharge.getOrderStatus().intValue() != 0) {
            return ServerResponse.createByErrorMsg("Order status cannot be modified repeatedly");
        }

        userRecharge.setOrderStatus(Integer.valueOf(2));
        int updateCCount = this.userRechargeMapper.updateByPrimaryKeySelective(userRecharge);
        if (updateCCount > 0) {
            return ServerResponse.createBySuccessMsg("Order Modified to Failed");
        }
        return ServerResponse.createByErrorMsg("The modification is abnormal.");
    }


    public ServerResponse chargeCancel(UserRecharge userRecharge) throws Exception {
        if (userRecharge.getOrderStatus().intValue() != 0) {
            return ServerResponse.createByErrorMsg("Order status cannot be modified repeatedly");
        }

        userRecharge.setOrderStatus(Integer.valueOf(3));
        int updateCCount = this.userRechargeMapper.updateByPrimaryKeySelective(userRecharge);
        if (updateCCount > 0) {
            return ServerResponse.createBySuccessMsg("The order was cancelled successfully.");
        }
        return ServerResponse.createByErrorMsg("The order cancellation is abnormal.");
    }


    public ServerResponse<PageInfo> findUserChargeList(String payChannel, String orderStatus, String orderSn, HttpServletRequest request, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);

        User user = this.iUserService.getCurrentRefreshUser(request);
        if (user == null) {
            return ServerResponse.createByErrorMsg("The user does not exist");
        }

        List<UserRecharge> userRecharges = this.userRechargeMapper.findUserChargeList(user.getId(), payChannel, orderStatus, orderSn);
//        for (UserRecharge item : userRecharges) {
//            String fname = "/order_voucher/" + item.getOrderSn() + ".jpg";
//            if (!FileUtil.exist(fname)) {
//                fname = "";
//            }
//            item.setFname(fname);
//        }

        log.info("充值列表，增加用户 {} ，payChannel = {} , orderStatus = {}， 数量 = {}", new Object[]{user.getId(), payChannel, orderStatus, userRecharges.size()});
        PageInfo pageInfo = new PageInfo(userRecharges);
        return ServerResponse.createBySuccess(pageInfo);
    }


    public ServerResponse<PageInfo> listByAgent(Integer agentId, String realName, String payChannel, Integer state, HttpServletRequest request, int pageNum, int pageSize) {
        AgentUser currentAgent = this.iAgentUserService.getCurrentAgent(request);

        if (agentId != null) {
            AgentUser agentUser = this.agentUserMapper.selectByPrimaryKey(agentId);
            if (!agentUser.getParentId().equals(currentAgent.getId())) {
                return ServerResponse.createByErrorMsg("Unable to query non-lower agent records");
            }
        }

        Integer searchId = null;
        if (agentId == null) {
            searchId = currentAgent.getId();
        } else {
            searchId = agentId;
        }


        PageHelper.startPage(pageNum, pageSize);


        List<UserRecharge> userRecharges = this.userRechargeMapper.listByAgent(searchId, realName, payChannel, state);

        PageInfo pageInfo = new PageInfo(userRecharges);

        return ServerResponse.createBySuccess(pageInfo);
    }


    public ServerResponse listByAdmin(String accountType, Integer agentId, String startAmount, String orderSn, Integer userId, String userPhone, String realName, Integer state, Integer payChannel, String beginTime, String endTime, HttpServletRequest request, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);


        Timestamp begin_time = null;
        if (StringUtils.isNotBlank(beginTime)) {
            begin_time = DateTimeUtil.searchStrToTimestamp(beginTime);
        }
        Timestamp end_time = null;
        if (StringUtils.isNotBlank(endTime)) {
            end_time = DateTimeUtil.searchStrToTimestamp(endTime);
        }

        String beginAmount = "";
        String endAmount = "";
        if (StringUtils.isNotBlank(startAmount)){
            String[] splitAmount = startAmount.split(",");
            List<String> amountList = Arrays.asList(splitAmount);
            if (amountList.size() == 2) {
                beginAmount = amountList.get(0);
                endAmount = amountList.get(1);
            }
        }

        List<UserRechargeVo> userRecharges = this.userRechargeMapper.listByAdmin(accountType, agentId, orderSn, userId, userPhone, realName, state, payChannel, begin_time, end_time, beginAmount, endAmount);
        PageInfo pageInfo = new PageInfo(userRecharges);
        return ServerResponse.createBySuccess(pageInfo);
    }


    @Transactional
    public ServerResponse updateState(Integer chargeId, String paySn, Integer state) throws Exception {
        UserRecharge userRecharge = this.userRechargeMapper.selectByPrimaryKey(chargeId);

        if (userRecharge == null) {
            return ServerResponse.createByErrorMsg("The recharge order does not exist.");
        }
        if (userRecharge.getOrderStatus() != 0) {
            return ServerResponse.createByErrorMsg("The order status is not the order status and cannot be changed.");
        }

        User user = this.userMapper.selectByPrimaryKey(userRecharge.getUserId());
        if (user == null) {
            return ServerResponse.createByErrorMsg("The user does not exist");
        }

        // 修改前的总金额和可用余额
        BigDecimal userAmt_before = user.getUserAmt();
        BigDecimal enableAmt_before = user.getEnableAmt();

        if (state == 1) {
            BigDecimal user_amt = user.getUserAmt().add(userRecharge.getPayAmt());
            log.info("管理员确认订单成功，增加用户 {} 总资金，原金额 = {} , 增加后 = {}", new Object[]{user.getId(), user.getUserAmt(), user_amt});
            BigDecimal user_enable_amt = user.getEnableAmt().add(userRecharge.getPayAmt());
            log.info("管理员确认订单成功，增加用户 {} 可用资金，原金额 = {} , 增加后 = {}", new Object[]{user.getId(), user.getEnableAmt(), user_enable_amt});
            user.setEnableAmt(user_enable_amt);
            int updateCount = this.userMapper.updateByPrimaryKeySelective(user);
            if (updateCount > 0) {
                log.info("修改用户资金成功！");
                // 充值金额
                BigDecimal payAmt = userRecharge.getPayAmt();

                // 查看是否有成功充值记录
                int recharge = userRechargeMapper.queryUserSuccessRecharge(user.getId());
                // 查询是否满足配置的任务 赠送积分
                bonusPoints(user.getId(), payAmt, recharge == 0 ? StIntegralTask.TASK_TYPE_FIRST_RECHARGE : StIntegralTask.TASK_TYPE_NORMAL_RECHARGE);

            } else {
                log.error("修改用户资金出错，抛出异常");
                throw new Exception("There was an error in modifying the user's funds and throwing an exception.");
            }
        }

        userRecharge.setOrderStatus(Integer.valueOf((state.intValue() == 1) ? 1 : 2));
        userRecharge.setPayTime(new Date());
        userRecharge.setPaySn(paySn);
        int updateCount = this.userRechargeMapper.updateByPrimaryKeySelective(userRecharge);
        if (updateCount > 0) {
            log.info("修改充值状态成功！");
        }

        // 记录充值流水
        if(state == 1){
            UserCashDetail ucd = new UserCashDetail();
            ucd.setAgentId(user.getAgentId());
            ucd.setAgentName(user.getAgentName());
            ucd.setUserId(user.getId());
            ucd.setUserName(user.getRealName());
            ucd.setDeType("User recharge");
            ucd.setDeAmt(userRecharge.getPayAmt());
            ucd.setDeSummary("The user recharges successfully, and the total amount before the recharge:" + userAmt_before
                    + ",userAmt:" + user.getUserAmt() + ",enableAmt_before:" + enableAmt_before + ",enableAmt:" + user.getEnableAmt());
            ucd.setAddTime(new Date());
            ucd.setIsRead(Integer.valueOf(0));
            int insertCount = this.userCashDetailMapper.insert(ucd);
        }

        log.info("记录充值流水成功！");
        // 发送邮箱
        if(SystemVersionEnum.global.name().equals(active)) {
            sendHTMLMail.sendRechargeEmail(user, userRecharge);
        }
        return ServerResponse.createBySuccessMsg("Modify the order status successfully！");
    }


    @Transactional
    public ServerResponse createOrder(Integer userId, Integer state, Integer amt, String payChannel, String file) {
        if (userId == null || state == null || amt == null) {
            return ServerResponse.createByErrorMsg("参数不能为空.");
        }

        User user = this.userMapper.selectByPrimaryKey(userId);
        if (user == null) {
            return ServerResponse.createByErrorMsg("找不到用户");
        }

        UserRecharge userRecharge = new UserRecharge();
        userRecharge.setUserId(user.getId());
        userRecharge.setNickName(user.getRealName());
        userRecharge.setAgentId(user.getAgentId());

        String ordersn = KeyUtils.getRechargeOrderSn();
        userRecharge.setOrderSn(ordersn);
        userRecharge.setOrderDesc(file);
        userRecharge.setPayChannel(payChannel);
        userRecharge.setPayAmt(new BigDecimal(amt.intValue()));
        userRecharge.setAddTime(new Date());
        userRecharge.setPayTime(new Date());

        if (state.intValue() == 0) {
            userRecharge.setOrderStatus(0);
        } else if (state.intValue() == 1) {
            // 充值成功
            userRecharge.setOrderSn(KeyUtils.getRechargeOrderSn());
            userRecharge.setPayChannel("2");
            userRecharge.setOrderStatus(1);

            // 更新用户金额
            user.setEnableAmt(user.getEnableAmt().add(new BigDecimal(amt.intValue())));
            this.userMapper.updateByPrimaryKeySelective(user);

            // 查看是否有成功充值记录
            int recharge = userRechargeMapper.queryUserSuccessRecharge(user.getId());
            // 查询是否满足配置的任务 赠送积分
            bonusPoints(user.getId(), new BigDecimal(amt), recharge < 1 ? StIntegralTask.TASK_TYPE_FIRST_RECHARGE : StIntegralTask.TASK_TYPE_NORMAL_RECHARGE);


        } else if (state.intValue() == 2) {
            userRecharge.setOrderStatus(2);
        } else {
            return ServerResponse.createByErrorMsg("订单状态不正确");
        }

        int insertCount = this.userRechargeMapper.insert(userRecharge);
        if (insertCount > 0) {
            // 记录充值流水
            if(state.intValue() == 1){
                // 修改前可用余额
                BigDecimal enableAmt_before = user.getEnableAmt();

                UserCashDetail ucd = new UserCashDetail();
                ucd.setAgentId(user.getAgentId());
                ucd.setAgentName(user.getAgentName());
                ucd.setUserId(user.getId());
                ucd.setUserName(user.getRealName());
                ucd.setDeType("系统充值");
                ucd.setDeAmt(userRecharge.getPayAmt());
                ucd.setDeSummary("用户充值成功，用户总资金：" + user.getUserAmt() + "，可用资金（变更前）：" + enableAmt_before + "，可用资金（变更后）：" + user.getEnableAmt());
                ucd.setAddTime(new Date());
                ucd.setIsRead(0);
                this.userCashDetailMapper.insert(ucd);
            }

            log.info("记录充值流水成功！");
            // 发送邮箱
            if(SystemVersionEnum.global.name().equals(active)) {
                sendHTMLMail.sendRechargeEmail(user, userRecharge);
            }

            return ServerResponse.createBySuccessMsg(ordersn);
        }
        return ServerResponse.createByErrorMsg("Failed to generate the order, please try again.");
    }


    public ServerResponse del(Integer cId) {
        if (cId == null) {
            return ServerResponse.createByErrorMsg("The ID cannot be empty.");
        }
        int updateCount = this.userRechargeMapper.deleteByPrimaryKey(cId);
        if (updateCount > 0) {
            return ServerResponse.createBySuccessMsg("Deleted successfully");
        }
        return ServerResponse.createByErrorMsg("Failed to delete");
    }


    public int deleteByUserId(Integer userId) {
        return this.userRechargeMapper.deleteByUserId(userId);
    }


    public BigDecimal CountChargeSumAmt(Integer chargeState) {
        return this.userRechargeMapper.CountChargeSumAmt(chargeState);
    }

    public BigDecimal CountTotalRechargeAmountByTime(Integer chargeState) {
        return this.userRechargeMapper.CountTotalRechargeAmountByTime(chargeState);
    }

    @Override
    public List<UserRechargeVo> exportByAdmin(String accountType, Integer agentId, String startAmount, String orderSn, Integer userId, String userPhone, String realName, Integer state,
                                              Integer payChannel,
                                              String beginTime, String endTime, HttpServletRequest request) {
        Timestamp begin_time = null;
        if (StringUtils.isNotBlank(beginTime)) {
            begin_time = DateTimeUtil.searchStrToTimestamp(beginTime);
        }
        Timestamp end_time = null;
        if (StringUtils.isNotBlank(endTime)) {
            end_time = DateTimeUtil.searchStrToTimestamp(endTime);
        }

        String beginAmount = "";
        String endAmount = "";
        if (StringUtils.isNotBlank(startAmount)){
            String[] splitAmount = startAmount.split(",");
            List<String> amountList = Arrays.asList(splitAmount);
            if (amountList.size() == 2) {
                beginAmount = amountList.get(0);
                endAmount = amountList.get(1);
            }
        }

        List<UserRechargeVo> userRecharges = this.userRechargeMapper.listByAdmin(accountType, agentId, orderSn, userId, userPhone, realName, state, payChannel, begin_time, end_time, beginAmount, endAmount);
        return userRecharges;
    }

    @Override
    @Transactional
    public ServerResponse updateRecharge(Integer id, Integer payAmt, String addTime, String payTime) {

        UserRecharge userRecharge = this.userRechargeMapper.selectByPrimaryKey(id);
        if (userRecharge == null) {
            return ServerResponse.createByErrorMsg("The recharge order does not exist.");
        }

        User user = this.userMapper.selectByPrimaryKey(userRecharge.getUserId());
        if (user == null) {
            return ServerResponse.createByErrorMsg("用户不存在");
        }

        // 设置时区
        Date dateTime = DateTimeUtil.strToDate(addTime);
        Date dateTime1 = DateTimeUtil.strToDate(payTime);
        userRecharge.setAddTime(dateTime);
        userRecharge.setPayTime(dateTime1);


        userRecharge.setPayAmt(new BigDecimal(payAmt));
        int updateCount = this.userRechargeMapper.updateByPrimaryKeySelective(userRecharge);


        // 新增修改的记录
        StringBuilder record = new StringBuilder();
        record.append("充值记录->订单号：" + userRecharge.getOrderSn() + "; ");
        record.append("修改时间：" + DateUtils.now() + ";");
        record.append("充值金额由" + userRecharge.getPayAmt() + "修改为" + payAmt + ";");
        record.append("订单创建时间由" + userRecharge.getAddTime() + "修改为" + dateTime + ";");
        record.append("订单支付时间由" + userRecharge.getPayTime() + "修改为" + dateTime1 + ";");

        // 修改记录
        LogEditTransactionRecords transactionRecords = new LogEditTransactionRecords();
        transactionRecords.setRecord(record.toString());
        transactionRecords.setOrderNo(userRecharge.getOrderSn() );
        transactionRecords.setCreateTime(new Date());
        logEditTransactionRecordsMapper.insert(transactionRecords);

        if (updateCount > 0) {
            return ServerResponse.createBySuccessMsg("Modify the order status successfully！");
        }
        return ServerResponse.createByErrorMsg("Failed to modify order status！");
    }

    // 充值赠送积分方法
    private void bonusPoints(Integer userId, BigDecimal amount, String taskType){
        StIntegralTask task = integralTaskMapper.queryTaskByType(taskType, amount);

        // 如果没有达到首次充值的条件 走普通的
        if ( StIntegralTask.TASK_TYPE_FIRST_RECHARGE.equals(taskType) && null == task) {
            task = integralTaskMapper.queryTaskByType(StIntegralTask.TASK_TYPE_NORMAL_RECHARGE, amount);
        }

        // 查询出该类型配置的最大值和最小值 然后判断充值金额满足  例如 充值1 元  最小值是10元 那么就不需要赠送  充值100  最大值是10 那么就需要按照最大值来赠送
        if (null == task) {
            StIntegralTask maxTask = integralTaskMapper.queryMaxByType(taskType);
            if (null != maxTask) {
                Integer maxNum = maxTask.getMaxNum();
                if(maxNum < amount.intValue()){
                    // 按照最大值赠送
                    Integer integral = maxTask.getIntegral();
                    iUserService.updateUserIntegral(userId, integral, taskType, true, maxTask.getId());
                }
            }
        }
        else {
            Integer integral = task.getIntegral();
            iUserService.updateUserIntegral(userId, integral, taskType, true, task.getId());
        }
    }

    public static void main(String[] args) {
        BigDecimal bigDecimal = new BigDecimal("2.22");
        System.out.println(bigDecimal.intValue());
    }
}
